package com.vanke.devops.domain.job;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.vanke.core.util.JsonUtil;
import com.vanke.core.util.RestClient;
import com.vanke.devops.domain.job.bean.ContainerWarn;
import com.vanke.devops.domain.manager.dingding.DingDingManager;
import com.vanke.devops.domain.manager.docker.DockerManager;
import com.vanke.devops.domain.manager.docker.bean.ContainerInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author 陈景阳
 * @since 2018/6/5
 */
@Component
public class ContainerMonitorJob implements InitializingBean{

    private static final Logger LOGGER = LoggerFactory.getLogger(ContainerMonitorJob.class);

    @Autowired
    private ExecutorService executorService;

    @Autowired
    private DockerManager dockerManager;

    @Autowired
    private DingDingManager dingDingManager;

    private Map<String,ContainerWarn> warnMap = Maps.newConcurrentMap();


    private BlockingQueue<ContainerInfo> queue = new LinkedBlockingQueue<>(1000);

    public void offer(ContainerInfo state){
        if(!this.queue.offer(state)){
            LOGGER.error("container state offer error");
        }
    }

    public void exec(String ips){
        String[] ipsArray = ips.split(",");
        List<String> ipList = Arrays.asList(ipsArray);
        ipList.forEach(ip -> {
            executorService.submit(() -> dockerManager.stats(ip));

        });
    }

    private void doLogic(){
        //TODO，阈值需要可以配置
        int targetValue = 80;
        while (true) {
            try {
                ContainerInfo containerInfo = queue.take();
                this.memoryWarn(containerInfo,targetValue);
                this.cpuWarn(containerInfo,targetValue);
            } catch (InterruptedException e) {
                this.doLogic();
            } catch (Exception e){
                e.printStackTrace();
                break;
            }
        }
    }

    private void cpuWarn(ContainerInfo containerInfo, int targetValue){
        String key = JobConstants.CPU_PREFIX + getContainerName(containerInfo.getContainerName());
        ContainerWarn containerWarn = warnMap.get(key);
        //cpu usage percent
        double cpuUsagePercent = containerInfo.getCpu().getUsagePercent() * 100;
        BigDecimal value = new BigDecimal(cpuUsagePercent);
        //warn is exist
        if(containerWarn != null){
            if(cpuUsagePercent < targetValue){
                String text = String.format(JobConstants.CPU_NORMAL,
                        containerInfo.getEndpointIp(),getContainerName(containerInfo.getContainerName()),
                        value.setScale(2,BigDecimal.ROUND_HALF_UP));
                dingDingManager.sendText(text);
                warnMap.remove(key);
            }
            return;
        }
        //warning
        if(cpuUsagePercent > targetValue){
            String text = String.format(JobConstants.CPU_WARN,
                    containerInfo.getEndpointIp(),getContainerName(containerInfo.getContainerName()),
                    value.setScale(2,BigDecimal.ROUND_HALF_UP));
            dingDingManager.sendText(text);
            ContainerWarn warn = new ContainerWarn(containerInfo.getContainerId());
            warnMap.put(key,warn);
        }
    }

    private void memoryWarn(ContainerInfo containerInfo, int targetValue){
        String key = JobConstants.MEM_PREFIX + getContainerName(containerInfo.getContainerName());
        ContainerWarn containerWarn = warnMap.get(key);
        //memory usage percent
        double memoryUsagePercent = containerInfo.getMemory().getUsagePercent() * 100;
        BigDecimal value = new BigDecimal(memoryUsagePercent);
        //warn is exist
        if(containerWarn != null){
            if(memoryUsagePercent < targetValue){
                String text = String.format(JobConstants.MEM_NORMAL,
                        containerInfo.getEndpointIp(),getContainerName(containerInfo.getContainerName()),
                        value.setScale(2,BigDecimal.ROUND_HALF_UP));
                dingDingManager.sendText(text);
                warnMap.remove(key);
            }
            return;
        }
        //warning
        if(memoryUsagePercent > targetValue){
            String text = String.format(JobConstants.MEM_WARN,
                    containerInfo.getEndpointIp(),getContainerName(containerInfo.getContainerName()),
                    value.setScale(2,BigDecimal.ROUND_HALF_UP));
            dingDingManager.sendText(text);
            ContainerWarn warn = new ContainerWarn(containerInfo.getContainerId());
            warnMap.put(key,warn);
        }
    }

    @Override
    public void afterPropertiesSet(){
        executorService.submit(this::doLogic);
    }

    private  String getContainerName(String containerName){
        int index = containerName.indexOf(".");
        if(index > 0){
            return containerName.substring(0,index);
        }
        return containerName;
    }
}
